# -*- coding: utf-8 -*- 

#from levin.ordereddict import OrderedDict
from collections import OrderedDict
import codecs
from wineObjects import BottleBase, Tasting, colors
import os, os.path
import tempfile
import levin.levinCommon as levinCommon
import cPickle as pk


VERSION = 0.1
import datetime
import difflib
import uuid

def uuidID():
    return uuid.uuid1().int

def timeId():
    dt = datetime.datetime
    oldnow = timeId._now
    now = dt.now()
    while( now == oldnow ) :
        now = dt.now()
    timeId._now = now        
    return int((now - dt(2010,1,1)).total_seconds())

timeId._now = datetime.datetime.now()

class OrderedDictWithLocal(OrderedDict):
    """An ordered dictionnary where keys have a translation to a locale.
    The dict can thus be queried with translated key.
    The values stored in this dict must have a 'localname' attribute"""
    notFound = object()
    def __init__(self, *la,**args):
        self.localD = OrderedDict()
        super(OrderedDictWithLocal,self).__init__(*la, **args)
        

    def update(self, other):
        self.localD.update(other.localD)
        super(OrderedDictWithLocal,self).update(other)
        
    def __getitem__(self, k):
        v = OrderedDict.get(self, k, OrderedDictWithLocal.notFound)
        if v is OrderedDictWithLocal.notFound:
            v = self.localD.get(k, OrderedDictWithLocal.notFound)
        if v is OrderedDictWithLocal.notFound:
            raise KeyError(k)
        return v

    def __setitem__(self, k,v):
        #print ' setting item ', k, ': ', v , v.localname
        if v.localname != "":
            self.localD[v.localname] = v
        OrderedDict.__setitem__(self,k,v)

    def pop(self, o , default = None):
        d=OrderedDict.pop(self, o , default)
        self.localD.pop(o, default)
        return d

    def get(self, k, default=None, checkLocal = False):
        try :
            return self.__getitem__(k)
        except KeyError :
            pass
        if checkLocal:
            try :
                return self.localD[k]
            except KeyError :
                pass
        return default
    
    def getApproximate(self, k , default=None, checkLocal = False):        
        v = self.get( k , None )
        if v is None:            
            l = difflib.get_close_matches(k, self.keys(), 1, cutoff=0.6)
            if l != [] :
                return self.get(l[0], default=default, checkLocal= checkLocal)
            elif checkLocal:
                l = difflib.get_close_matches(k, self.localD.keys(), 1, cutoff=0.6)
                if l != [] :
                    return self.get(l[0], default=default, checkLocal= checkLocal)
        else :
            return v
        return default
        

# baseSystem provides the base class dependending on the uderlying graphic
# system used. 
from levin.baseSystem import BaseClass
# BaseClass is kivy.EventDispatcher if using kivy, else BaseClass

class AttributeHolder(BaseClass):
    """ A base class to define wrapper around attributes.

     each class defines one attribute, ex 'foo',
     - have a user dedicated member identified by '_user' (ex: attributes '_foo' and '_foo_user')
     - when a client class modifies the attribute, reacting to a user input,  'self._foo_user' is created and
     affected. Not 'cls._foo_user' (the later being here just as a placeholder, and never saved).
     - only 'self._foo_user' attributes are saved.

     This base class implements the common functionnalities :
      - creation of the '_user' attribute (AttributeHolder class must call buildUserAttr when needed)
      - check if the user attribute already exists

     Concrete implementations must implement an accessor function 'foo(..any args...)'
     """
    attname = ''
    attributeBuilder = None

    modified = False
    @classmethod
    def hasAttr(cls, self, user):
        aname = '_user_'+cls.attname if user else '_system_'+cls.attname
        return getattr(self, aname) is not None

    @classmethod
    def attributeMemberName(cls):
        return '_'+cls.attname

    
    @classmethod
    def buildAttr(cls,self, user):
        if cls.hasUserAttr(self,user):
            return
        # create an attribute        
        aname = '_user_'+cls.attributeMemberName() if user else '_system_'+cls.attributeMemberName()
        setattr(self,aname, cls.attributeBuilder() )

    def getUserAttRec(self, attname):
        att = getattr(self, '_user_'+attname)
        if  att is None and self.parentArea:
            return self.parentArea.getUserAttRec(attname)
        return att
    def getSysAttRec(self, attname):
        att = getattr(self, '_system_'+attname)
        if  att is None and self.parentArea:
            return self.parentArea.getSysAttRec(attname)
        return att
    
def attributeMaker(attname, attbuilder):
    """ Intended to be used as a class decorator for classes inheriting AttributeHolder.
    attname : str, the attribute name the class describes. a attname method and _attname member are genrated.
    attbuilder : a function taking 1 arg, returning a new attribute (the real attribute object, ex: a list, a dict,...)
    """
    def addAtt(cls):
        """cls is a class inheriting AttributeHolder.
        Returns a concrete class inheriting cls but with additionnal build/get/has attribute functions generated from
        attname and attbuilder
        """
        cls.attname = attname
        cls.attributeBuilder = staticmethod(attbuilder)
        #setattr(cls,attname, getattr(cls,attname+'_base' ) )
        useratt = '_user_'+attname
        sysatt = '_system_'+attname
        setattr(cls,useratt, None)
        setattr(cls, sysatt, None)


        # generate the '_has_attname' method for this class cls.
        def hasAttr(self, user):
            aname = useratt if user else sysatt
            return getattr(self, aname) is not None
        setattr(cls, '_has_'+attname, hasAttr)

        # generate the '_build_attname' method for class cls.
        # _buils_attname function creates and returns a new user or system attribute if not already existing.
        def buildAttr(self, user):
            aname = useratt if user else sysatt
            if getattr(self, aname) is not None:
                return getattr(self, aname)
            att = attbuilder() 
            setattr(self,aname,att)
            return att
        setattr(cls, '_build_'+attname, buildAttr)


        # generate the '_get_system_attname' method for  class cls.
        if cls.inherited :
            setattr(cls,'_get'+useratt, lambda self : self.getUserAttRec(attname) )
            setattr(cls,'_get'+sysatt, lambda self : self.getSysAttRec(attname) )                    
        else:
            setattr(cls,'_get'+useratt, lambda self : getattr(self,useratt) )
            setattr(cls,'_get'+sysatt, lambda self :  getattr(self, sysatt) )                    

        class _cls(cls):
            def __new__(typ, *args, **kwargs):
                obj = super(cls, typ).__new__(typ, *args, **kwargs)
                setattr(obj,useratt, None)
                setattr(obj, sysatt, None)
                return obj            

        _cls.__name__ = cls.__name__
        return _cls
    return addAtt
